package com.yjzx.util.common.util.BeanUtils;

import java.io.File;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author yjzx
 * @date 2024/8/14
 * @description LambdaSerializable
 */
public interface LambdaSerializable extends Serializable {
    String PREFIX_GETTER_IS = "is";
    String PREFIX_GETTER_GETTER = "get";
    String PREFIX_SETTER = "set";

    /**
     * 获取SerializedLambda
     *
     * @return
     */
    default SerializedLambda getSerializedLambda() {
        SerializedLambda serializedLambda = null;
        try {
            // 获取 lambda 实例的 writeReplace 方法
            Method serializedLambdaMethod = this.getClass().getDeclaredMethod("writeReplace");
            serializedLambdaMethod.setAccessible(true);

            // 执行 writeReplace 方法，获取 SerializedLambda 对象
            serializedLambda = (SerializedLambda) serializedLambdaMethod.invoke(this);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        return serializedLambda;
    }

    /**
     * 获取生成lambda的类
     *
     * @return
     */
    default Class<?> getClassFromLambda() {
        Class<?> declaringClass;
        String implClass = getSerializedLambda().getImplClass();
        try {
            // 获取方法所在类
            declaringClass = getClassByClassName(implClass);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return declaringClass;
    }

    /**
     * 根据类名获取类
     *
     * @param className
     * @return
     * @throws ClassNotFoundException
     */
    default Class<?> getClassByClassName(String className) throws ClassNotFoundException {
        final char separatorChar = File.separatorChar;
        char[] chars = className.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == separatorChar || chars[i] == '/') {
                chars[i] = '.';
            }
        }
        String clazz = new String(chars).intern();
        switch (clazz) {
            case "Z":
                return boolean.class;
            case "B":
                return byte.class;
            case "C":
                return char.class;
            case "S":
                return short.class;
            case "I":
                return int.class;
            case "J":
                return long.class;
            case "F":
                return float.class;
            case "D":
                return double.class;
            case "V":
                return void.class;
            default:
                return Class.forName(clazz);
        }

    }

    /**
     * 获取生成lambda的方法
     *
     * @return
     */
    default Method getMethodFromLambda() {
        Method method = null;
        try {
            SerializedLambda serializedLambda = getSerializedLambda();
            // 获取方法名称
            String methodName = serializedLambda.getImplMethodName();

            // 获取方法所在类
            Class<?> declaringClass = getClassByClassName(serializedLambda.getImplClass());
            // 获取方法签名
            String signature = serializedLambda.getImplMethodSignature();
            // 从方法签名中解析参数类型
            String[] classNames = parseParameterTypes(signature);
            // 获取方法的参数类型
            Class<?>[] parameterClasses = new Class<?>[classNames.length];

            for (int i = 0; i < classNames.length; i++) {
                if (!classNames[i].isEmpty()) {
                    parameterClasses[i] = getClassByClassName(classNames[i]);
                }
            }
            // 使用反射获取 Method 对象
            method = declaringClass.getMethod(methodName, parameterClasses);
        } catch (NoSuchMethodException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return method;
    }

    /**
     * 从方法签名中解析参数类型。
     *
     * @param signature 方法签名字符串
     * @return 参数类型的数组
     */
    default String[] parseParameterTypes(String signature) {
        int start = signature.indexOf('(') + 1;
        int end = signature.indexOf(')');
        String paramsPart = signature.substring(start, end);
        if (paramsPart.isEmpty()) {
            return new String[0];
        }
        String[] parameterSignatures = paramsPart.split("[;,]");
        String[] parameterTypes = new String[parameterSignatures.length];

        for (int i = 0; i < parameterSignatures.length; i++) {
            String paramSig = parameterSignatures[i].trim();
            if (paramSig.startsWith("L")) {
                // 对象类型
                parameterTypes[i] = paramSig.substring(1).trim();
            } else {
                parameterTypes[i] = paramSig;
            }

        }

        return parameterTypes;
    }
}
